#pragma once
#include <list>
#include <vector>
#include "kernel/feInterpolation.h"
#include <math.h>
using namespace std;



//------------------------------------------------------------------------------------------------------
class VectorCache
{
	struct XvPair
	{
		double X;
		vector<double> V;
	};


	list<XvPair> Data;


public:

	void PushV(double iR, vector<double> &iV)
	{
		XvPair p;
		p.X = iR;
		p.V = iV;


		//try to insert 
		list<XvPair>::iterator it = Data.begin();
		for(; it!=Data.end(); ++it)
		{
			if(it->X > iR)
			{
				Data.insert(it, p);
				return;
			}
		}


		//add to the end
		Data.push_back(p);
	}


	//-----------------------------------------------------------------------------------------------------------------------
	void PushV(double iX, double iY, double iZ, vector<double> &iV)
	{
		double r = 1e10*iX + 1e5*iY + iZ;
		XvPair p;
		p.X = r;
		p.V = iV;


		//try to insert 
		list<XvPair>::iterator it = Data.begin();
		for(; it!=Data.end(); ++it)
		{
			if(it->X > r)
			{
				Data.insert(it, p);
				return;
			}
		}


		//add to the end
		Data.push_back(p);
	}


	//-----------------------------------------------------------------------------------------------------------------------
	bool GetV(double iX, double iY, double iZ, double iEps, vector<double> &oV)
	{
		if(Data.size() < 2) return false;

		double r = 1e10*iX + 1e5*iY + iZ;


		//search for indeces
		list<XvPair>::iterator it = Data.begin();
		list<XvPair>::iterator it1 = Data.begin();
		list<XvPair>::iterator it2 = Data.begin();


		//linear search!
		for(; it!=Data.end(); ++it)
		{
			if(it->X > r)
			{
				it2 = it;
				if(fabs(it1->X - it2->X) > iEps) return false;
			}
			it1 = it2 = it;
		}
		

		return true;
	}


	//-----------------------------------------------------------------------------------------------------------------------
	bool GetV(double iR, double iEps, vector<double> &oV)
	{
		if(Data.size() < 2) return false;

		//search for indeces
		list<XvPair>::iterator it = Data.begin();
		list<XvPair>::iterator it1 = Data.begin();
		list<XvPair>::iterator it2 = Data.begin();


		//linear search!
		for(; it!=Data.end(); ++it)
		{
			if(it->X > iR)
			{
				it2 = it;
				if(fabs(it1->X - it2->X) > iEps) return false;
			}
			it1 = it2 = it;
		}

		if(it1 == it2) return false;

		//linear interpolation
		double x[2] = { it1->X, it2->X };
		double l1 = feInterpolation::LinearBasis1(it1->X, it2->X, iR);
		double l2 = feInterpolation::LinearBasis2(it1->X, it2->X, iR);


		//fill result
		oV.clear();
		for(unsigned int i=0; i<it1->V.size(); i++)
			oV[i] = it1->V[i]*l1 + it2->V[i]*l2;

		return true;
	}


	//-----------------------------------------------------------------------------------------------------------------------
	void Clear()
	{
		Data.clear();
	}
};